﻿#region

using System.Text.Json;
using System.Text.Json.Nodes;

#endregion

namespace Vin.Tool.Core.JsonCategory;

public static class VinJsonExtension
{
    /// <summary>
    /// 初始化JsonSerializerOptions
    /// </summary>
    /// <param name="options"></param>
    /// <param name="type"></param>
    public static void InitJsonSerializerOptions(this JsonSerializerOptions options,
        JsonTool.JsonOptionsType type = JsonTool.JsonOptionsType.CamelCase)
    {
        // 如需改动 JsonTool.GenerateJsonOptions 方法 也许跟随改动
        var tempOptions = JsonTool.GenerateJsonOptions(type);

        options.DefaultIgnoreCondition = tempOptions.DefaultIgnoreCondition;
        options.ReferenceHandler = tempOptions.ReferenceHandler;
        options.ReadCommentHandling = tempOptions.ReadCommentHandling;
        options.AllowTrailingCommas = tempOptions.AllowTrailingCommas;
        options.NumberHandling = tempOptions.NumberHandling;
        options.PropertyNameCaseInsensitive = tempOptions.PropertyNameCaseInsensitive;

        foreach (var tempOptionsConverter in tempOptions.Converters)
        {
            options.Converters.Add(tempOptionsConverter);
        }

        options.PropertyNamingPolicy = tempOptions.PropertyNamingPolicy;
    }

    public static JsonDocument ToJsonDocument(this string jsonData)
    {
        return JsonDocument.Parse(jsonData);
    }

    public static JsonElement ToJsonElement(this string jsonData)
    {
        return JsonDocument.Parse(jsonData).RootElement;
    }

    public static JsonElement ToJsonElement(this object? objData)
    {
        if (objData == null) return default;
        if (objData is string) return ((string)objData).ToJsonElement();
        return JsonSerializer.SerializeToElement(objData, JsonTool.DefaultOptions);
    }

    public static JsonNode? ToJsonNode(this string jsonData)
    {
        try
        {
            return JsonNode.Parse(jsonData);
        }
        catch
        {
            return null;
        }
    }

    public static T? ToObject<T>(this string jsonData, JsonSerializerOptions? options = null)
    {
        return (T?)jsonData.ToObject(typeof(T), options ?? JsonTool.DefaultOptions);
    }

    public static T? ToObject<T>(this JsonElement? element, JsonSerializerOptions? options = null)
    {
        if (element == null) return default;
        return JsonSerializer.Deserialize<T>(element.Value, options ?? JsonTool.DefaultOptions);
    }

    public static T? ToObject<T>(this object? element, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Deserialize<T>(element.ToJsonElement(), options ?? JsonTool.DefaultOptions);
    }
    
    public static object? ToObject(this JsonNode? element, Type type, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Deserialize(element, type, options ?? JsonTool.DefaultOptions);
    }

    public static object? ToObject(this object? element, Type type, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Deserialize(element.ToJsonElement(), type, options ?? JsonTool.DefaultOptions);
    }

    public static object? ToObject(this string jsonData, Type type, JsonSerializerOptions? options)
    {
        if (string.IsNullOrEmpty(jsonData)) return null;
        // 如果T是string类型，直接返回
        if (type == typeof(string)) return jsonData;
        return JsonSerializer.Deserialize(jsonData, type, options);
    }

    public static string ToJson(this object? obj, JsonSerializerOptions? options = null)
    {
        if (obj == null) return string.Empty;
        if (obj is string) return (string)obj;
        return JsonSerializer.Serialize(obj, options ?? JsonTool.DefaultOptions);
    }

    /// <summary>
    /// 将Json字符串转换为对象（小驼峰）
    /// </summary>
    /// <param name="jsonData"></param>
    /// <param name="options"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T? ToCamelCaseObject<T>(this string jsonData, JsonSerializerOptions? options = null)
    {
        return jsonData.ToObject<T>(options);
    }

    public static object? ToCamelCaseObject(this string jsonData, Type type, JsonSerializerOptions? options = null)
    {
        // if (string.IsNullOrEmpty(jsonData)) return null;
        // // 如果T是string类型，直接返回
        // if (type == typeof(string)) return jsonData;
        // return JsonSerializer.Deserialize(jsonData, type, options ?? JsonTool.CamelCaseOptions);
        return jsonData.ToObject(type, options ?? JsonTool.CamelCaseOptions);
    }

    /// <summary>
    /// 将对象转换为Json字符串（小驼峰）
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static string ToCamelCaseJson(this object? obj, JsonSerializerOptions? options = null)
    {
        if (obj == null) return string.Empty;
        if (obj is string) return (string)obj;
        return JsonSerializer.Serialize(obj, options ?? JsonTool.CamelCaseOptions);
    }

    /// <summary>
    /// 将Json字符串转换为对象（下划线）
    /// </summary>
    /// <param name="jsonData"></param>
    /// <param name="defaultType"></param>
    /// <param name="options"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T? ToUnderLineObject<T>(this string jsonData,
        JsonTool.JsonOptionsType defaultType = JsonTool.JsonOptionsType.UnderLineLower,
        JsonSerializerOptions? options = null)
    {
        if (string.IsNullOrEmpty(jsonData)) return default(T);
        return JsonSerializer.Deserialize<T>(jsonData,
            options ?? (defaultType == JsonTool.JsonOptionsType.UnderLineLower
                ? JsonTool.UnderLineLowerOptions
                : JsonTool.UnderLineUpperOptions));
    }

    /// <summary>
    /// 将对象转换为Json字符串（下划线）
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="defaultType"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static string ToUnderLineJson(this object? obj,
        JsonTool.JsonOptionsType defaultType = JsonTool.JsonOptionsType.UnderLineLower,
        JsonSerializerOptions? options = null)
    {
        if (obj == null) return string.Empty;
        if (obj is string) return (string)obj;
        return JsonSerializer.Serialize(obj, options ?? (defaultType == JsonTool.JsonOptionsType.UnderLineLower
            ? JsonTool.UnderLineLowerOptions
            : JsonTool.UnderLineUpperOptions));
    }

    /// <summary>
    /// 将Json字符串转换为对象（中划线）
    /// </summary>
    /// <param name="jsonData"></param>
    /// <param name="defaultType"></param>
    /// <param name="options"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T? ToMiddleLineObject<T>(this string jsonData,
        JsonTool.JsonOptionsType defaultType = JsonTool.JsonOptionsType.MiddleLineLower,
        JsonSerializerOptions? options = null)
    {
        if (string.IsNullOrEmpty(jsonData)) return default(T);
        return JsonSerializer.Deserialize<T>(jsonData,
            options ?? (defaultType == JsonTool.JsonOptionsType.MiddleLineLower
                ? JsonTool.MiddleLineLowerOptions
                : JsonTool.MiddleLineUpperOptions));
    }

    /// <summary>
    /// 将Json字符串转换为对象（中划线）
    /// </summary>
    /// <param name="obj"></param>
    /// <param name="defaultType"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static string ToMiddleLineJson(this object? obj,
        JsonTool.JsonOptionsType defaultType = JsonTool.JsonOptionsType.MiddleLineLower,
        JsonSerializerOptions? options = null)
    {
        if (obj == null) return string.Empty;
        if (obj is string) return (string)obj;
        return JsonSerializer.Serialize(obj, options ?? (defaultType == JsonTool.JsonOptionsType.MiddleLineLower
            ? JsonTool.MiddleLineLowerOptions
            : JsonTool.MiddleLineUpperOptions));
    }
}